package com.ztstech.ali_vod_video.alivideo.domain;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.alibaba.sdk.android.vod.upload.VODUploadCallback;
import com.alibaba.sdk.android.vod.upload.VODUploadClient;
import com.alibaba.sdk.android.vod.upload.VODUploadClientImpl;
import com.alibaba.sdk.android.vod.upload.model.UploadFileInfo;
import com.alibaba.sdk.android.vod.upload.model.VodInfo;
import com.aliyun.vod.log.core.AliyunLoggerManager;
import com.ztstech.ali_vod_video.alivideo.bean.VideoInfoBean;
import com.google.gson.Gson;
import com.ztstech.ali_vod_video.alivideo.base.BaseCallBack;
import com.ztstech.ali_vod_video.alivideo.bean.AuthResponseBean;
import com.ztstech.ali_vod_video.alivideo.constant.Constant;
import com.ztstech.ali_vod_video.alivideo.utils.LogUtil;
import com.ztstech.ali_vod_video.alivideo.utils.OkHttpUtil;
import com.ztstech.ali_vod_video.alivideo.utils.Base64;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;


import okhttp3.Response;

import static android.os.Environment.DIRECTORY_MOVIES;

/**
 * 视频vod上传
 */
public class AliVideoModelImpl implements AliVideoModel {

    private static final String TAG = "AliVideoModelImpl";

    public static String VOD_REGION = "cn-shenzhen";
    public static String RESULT_URL = "https://video.lemontry.com/";
    public static boolean VOD_RECORD_UPLOAD_PROGRESS_ENABLED = true;
    private final int MAX_REQUEST_NUM=50;

    public AliVideoModelImpl() {
        LogUtil.i("初始化 ------------------" + this.toString());
    }

    private VODUploadClient uploader;

    /**
     * 已经循环遍历了几次 超过10次就不请求了
     */
    private int num;
    /**
     * 当前文件下标
     */
    private int index = 0;

    /**
     * 供外界调用的上传方法 包含上传凭证获取、上传文件、获取播放地址是三个步骤，最终成功直接将视频地址返回给调用端
     *
     * @param appContext
     * @param path
     * @param baseCallBack
     */
    @Override
    public void upLoadVideo(final Context appContext, final String cateId, final String templateGroupId,
                            final String definition, final String path, String userData, final boolean needProgress,
                            final BaseCallBack<Map<String,String>> baseCallBack) {
        Map<String, String> map = new HashMap<>();
        //标题 当前时间+随机数
        final String title = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_" + (int)((new Random().nextDouble()*(99999-10000 + 1))+ 10000)+".mp4";
        map.put("fileName", title);
        map.put("title", title);
        if(TextUtils.isEmpty(templateGroupId)){
            map.put("templateGroupId", "8cae871c81c42affda3dd93b8533e729");
        }else {
            map.put("templateGroupId", templateGroupId);
        }
        map.put("cateId", cateId);
        map.put("userData", userData);
        baseCallBack.onProgress(0);
        AliyunLoggerManager.toggleLogger(false);
        uploader = new VODUploadClientImpl(appContext);
        OkHttpUtil.postRawJson(Constant.APP_GET_ACCESS_AUTH, new Gson().toJson(map), new BaseCallBack<String>() {
            @Override
            public void onSuccess(String response) {
                AuthResponseBean bean = new Gson().fromJson(response, AuthResponseBean.class);
                if (bean == null) {
                    baseCallBack.onFail("上传凭证获取失败");
                    return;
                }
                if(bean.isSucceed()){
                    Log.e(TAG, "上传凭证的videoId: " + bean.data.videoId);
                    upload(appContext, Integer.parseInt(cateId), templateGroupId, definition, path,
                            title, needProgress, bean, baseCallBack);
                }else {
                    baseCallBack.onFail(bean.getErrmsg());
                    return;
                }
            }

            @Override
            public void onFail(String msg) {
                baseCallBack.onFail(msg);
            }

            @Override
            public void onProgress(float percent) {
                Log.e(TAG, "上传进度: " + percent);
            }
        });
    }

    private void upload(Context context, final int cateId, final String templateGroupId,
                        final String definition, final String path, String title, final boolean needProgress,
                        final AuthResponseBean bean, final BaseCallBack<Map<String,String>> baseCallBack) {
        AliyunLoggerManager.toggleLogger(false);

        final VodInfo vodInfo = new VodInfo();
        vodInfo.setTitle("" + title);
        vodInfo.setDesc("");
        vodInfo.setCateId(cateId);
        vodInfo.setIsProcess(true);
        vodInfo.setIsShowWaterMark(false);
        vodInfo.setPriority(7);
        uploader.addFile(path, vodInfo);
        if(TextUtils.isEmpty(templateGroupId)){
            uploader.setTemplateGroupId("8cae871c81c42affda3dd93b8533e729");
        }else {
            uploader.setTemplateGroupId(templateGroupId);
        }
        uploader.setRegion(VOD_REGION);
        uploader.setPartSize(1024 * 1024);
        uploader.setRecordUploadProgressEnabled(VOD_RECORD_UPLOAD_PROGRESS_ENABLED);
        VODUploadCallback callback = new VODUploadCallback() {
            @Override
            public void onUploadSucceed(UploadFileInfo info) {
                LogUtil.i("onsucceed ------------------" + new Gson().toJson(info));
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(needProgress){
                    Map map=new HashMap();
                    map.put("url", RESULT_URL + info.getObject());
                    map.put("videoId", bean.data.videoId);
                    baseCallBack.onSuccess(map);
                }else {
                    getPlayUrl(bean.data.videoId, definition, baseCallBack);
                }
//                map.put("videoId", vid);
//                map.put("fileSize", bean.getFileSizeByDefinition("HD"));
//                map.put("sdVideo", bean.getPlayUrlByDefinition("SD"));
//                map.put("sdStorage", bean.getFileSizeByDefinition("SD"));
//                map.put("coverUrl", bean.getCoverUrl());
//                getPlayUrl(bean.data.videoId, definition, baseCallBack);
            }

            @Override
            public void onUploadFailed(UploadFileInfo info, String code, String message) {
                LogUtil.e("onfailed ------------------ " + info.getFilePath() + " " + code + " " + message);
                baseCallBack.onFail(code + message);
            }

            @Override
            public void onUploadProgress(UploadFileInfo info, long uploadedSize, long totalSize) {
                if (totalSize != 0) {
                    if (uploadedSize == totalSize) {
                        baseCallBack.onProgress(99);
                    } else {
                        baseCallBack.onProgress(uploadedSize * 100 / totalSize);
                    }
                }
                if(!needProgress){
                    LogUtil.i("onProgress ------------------ " + info.getFilePath() + " " + uploadedSize + " " + totalSize);
                }
            }

            @Override
            public void onUploadTokenExpired() {
                LogUtil.e("onExpired ------------- token失效");
                refreshToken(bean.data.videoId, baseCallBack);
            }

            @Override
            public void onUploadRetry(String code, String message) {
                LogUtil.e("onUploadRetry ------------- ");
                baseCallBack.onFail(code + message);
            }

            @Override
            public void onUploadRetryResume() {
                LogUtil.e("onUploadRetryResume ------------- ");
            }

            @Override
            public void onUploadStarted(UploadFileInfo uploadFileInfo) {
                LogUtil.i("onUploadStarted ------------- ");
                uploader.setUploadAuthAndAddress(uploadFileInfo, bean.data.uploadAuth, bean.data.uploadAddress);
                LogUtil.i("file path:" + uploadFileInfo.getFilePath() +
                        ", endpoint: " + uploadFileInfo.getEndpoint() +
                        ", bucket:" + uploadFileInfo.getBucket() +
                        ", object:" + uploadFileInfo.getObject() +
                        ", status:" + uploadFileInfo.getStatus());
            }
        };
        uploader.init(callback);
        uploader.start();
    }


    @Override
    public void upLoadVideoWithCompass(final Context appContext, String cateId, String templateGroupId,
                                       final String definition, String path, String userData, final boolean needProgress,
                                       final BaseCallBack<Map<String,String>> baseCallBack) {
        File video = new File(path);

        if (video.exists() && video.isFile()) {
            try {
                FileInputStream fileInputStream = new FileInputStream(video);
                long sizeMB = fileInputStream.getChannel().size() / (1024 * 1024);
                Log.e(TAG, "当前视频大小" + sizeMB + "MB");
                if (sizeMB > 200) {
                    //大于200MB 时执行压缩
                    final String desFilePath = appContext.getExternalFilesDir(DIRECTORY_MOVIES).getAbsolutePath() + File.separator + video.getName() + System.currentTimeMillis() + ".mp4";
//                    VideoCompress.compressVideoAutoScale(path, desFilePath, new VideoCompress.CompressListener() {
//                        @Override
//                        public void onStart() {
//                            Log.e(TAG, "压缩视频开始");
//                        }
//
//                        @Override
//                        public void onSuccess() {
//                            Log.e(TAG, "压缩视频成功");
//                            upLoadVideo(appContext, desFilePath, baseCallBack);
//                        }
//
//                        @Override
//                        public void onFail() {
//                            Log.e(TAG, "压缩视频失败，直接上传");
//                            upLoadVideo(appContext, desFilePath, baseCallBack);
//                        }
//
//                        @Override
//                        public void onProgress(float percent) {
//                            Log.e(TAG, "压缩视频进度: " + percent);
//                        }
//                    });

                } else {
                    upLoadVideo(appContext, cateId, templateGroupId, definition, path, userData, needProgress, baseCallBack);
                }


            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            upLoadVideo(appContext, cateId, templateGroupId, definition, path, userData, needProgress, baseCallBack);
        }
    }

    @Override
    public void cancelUpLoadVideo() {
        if(uploader != null){
            uploader.stop();
            uploader.clearFiles();
        }
    }


    /**
     * 凭证失效 刷新凭证
     *
     * @param videoId
     * @param callBack
     */
    private void refreshToken(final String videoId, final BaseCallBack<Map<String,String>> callBack) {
        Map<String, String> map = new HashMap<>();
        map.put("videoId", videoId);
        OkHttpUtil.requestNet(Constant.APP_REFRESH_ACCESS_AUTH, map, new BaseCallBack<String>() {
            @Override
            public void onSuccess(String response) {

                AuthResponseBean bean = new Gson().fromJson(response, AuthResponseBean.class);
                if (bean == null) {
                    return;
                }
                if (bean == null) {
                    return;
                }
                if (bean.isSucceed()) {
                    uploader.resumeWithAuth(bean.data.uploadAuth);
                } else {
                    callBack.onFail(bean.getErrmsg());
                }
            }

            @Override
            public void onFail(String msg) {
                callBack.onFail(msg);
            }

            @Override
            public void onProgress(float percent) {

            }
        });
    }

    /**
     * 获取播放地址
     * @param vid
     * @param callBack
     */
    public void getPlayUrl(final String vid, final String definition, final BaseCallBack<Map<String,String>> callBack) {
        /*
         * {
         * 	"authTimeout": "",
         * 	"definition": "",
         * 	"formats": "",
         * 	"outputType": "",
         * 	"playConfig": "",
         * 	"reAuthInfo": "",
         * 	"resultType": "",
         * 	"streamType": "",
         * 	"videoId": ""
         * }
         */

        Map<String, String> map = new HashMap<>();
        map.put("videoId", vid);
        if(TextUtils.isEmpty(definition)){
            map.put("definition", "SD");
        }else {
            map.put("definition", definition);
        }
        String mapJson = new Gson().toJson(map);
        Log.e(TAG, "获取视频地址参数：" + mapJson);
//        map.put("Definition", "SD");

        OkHttpUtil.postRawJson(Constant.APP_GET_VIDEO_PATH, mapJson, new BaseCallBack<String>() {
            @Override
            public void onSuccess(String response) {
                VideoInfoBean bean= new Gson().fromJson(response, VideoInfoBean.class);
                Log.e(TAG, "获取视频地址成功回调：" + response);
                if (bean == null) {
                    return;
                }
                int length = 1;
                if(!TextUtils.isEmpty(definition)){
                    length = definition.split(",").length;
                }
//                if (bean.isSucceed() && bean.data.playInfoList.size() == length) {
                if(bean.isSucceed()){
                    // 去掉视频地址中拼接的参数 最后得到的地址是 https：//aliiyunxxxxxxx.mp4样式
                    Map map=new HashMap();
                    map.put("videoId", vid);
                    map.put("url", bean.getPlayUrlByDefinition("HD"));
                    map.put("fileSize", bean.getFileSizeByDefinition("HD"));

                    map.put("sdVideo", bean.getPlayUrlByDefinition("SD"));
                    map.put("sdStorage", bean.getFileSizeByDefinition("SD"));
                    map.put("coverUrl", bean.getCoverUrl());
                    callBack.onSuccess(map);
                } else {
                    // TODO: 由于需要转码 有可能返回失败 所以遍历等待转码成功 这里要换成后台来操作
                    if (num < MAX_REQUEST_NUM) {
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        num = num + 1;
                        getPlayUrl(vid, definition, callBack);
                    } else {
                        callBack.onFail(bean.getErrmsg());
                    }
                }
            }

            @Override
            public void onFail(String msg) {
                callBack.onFail(msg);
            }

            @Override
            public void onProgress(float percent) {

            }
        });
    }
}
